package cn.com.connext.scrm.service;

import cn.com.connext.scrm.config.Constants;
import cn.com.connext.scrm.domain.json.BaseInfo;
import cn.com.connext.scrm.domain.master.Coupon;
import cn.com.connext.scrm.domain.master.CrmCoupon;
import cn.com.connext.scrm.domain.master.Product;
import cn.com.connext.scrm.repository.master.CouponRepository;
import cn.com.connext.scrm.repository.master.CrmCouponRepository;
import cn.com.connext.scrm.repository.master.ProductRepository;
import cn.com.connext.scrm.service.dto.CouponCrmDTO;
import cn.com.connext.scrm.service.dto.CouponDTO;
import cn.com.connext.scrm.service.dto.JsonResult;
import cn.com.connext.scrm.service.mapper.CouponService;
import cn.com.connext.scrm.utils.EntityUtils;
import cn.com.connext.scrm.web.rest.req.BasePageReq;
import cn.com.connext.scrm.web.rest.req.CouponPagesReq;
import cn.com.connext.scrm.web.rest.resp.CouponListResp;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Predicate;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class CouponServiceImpl implements CouponService {
    private final Logger log = LoggerFactory.getLogger(CouponServiceImpl.class);
    @Autowired
    private AnalysisExcel analysisExcel;

    @Autowired
    private CouponRepository couponRepository;

    private RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private AccessTokenImpl accessTokenImpl;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private CrmCouponRepository crmCouponRepository;


    @Override
    public JsonResult addCoupon(MultipartFile file, String productId) {
        List<CouponDTO> couponDTOList = analysisExcel.importExcelFile(file);
        log.info("通过上传excel添加有赞卷，个数: {}", couponDTOList.size());
        List<Coupon> couponList = EntityUtils.dtoList2PojoList(couponDTOList, Coupon.class);
        List<Coupon> result = new ArrayList<>();
        //防止优惠卷提供重复
        couponList.forEach(c -> {
                c.setProductId(productId);
                result.add(c);
        });
        //保存有赞卷
        couponRepository.save(result);
        //保存库存
        Product product = productRepository.findOne(productId);
        product.setStock(CollectionUtils.isEmpty(result) ? 0 : result.size());
        product.setIsAlive(0);
        productRepository.saveAndFlush(product);
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(0);
        return jsonResult;
    }

    @Override
    public JsonResult list() {
        JsonResult jsonResult = new JsonResult();
        //查询有效期内未使用的优惠卷
        List<Coupon> couponList = couponRepository.getPostActivityForAnswers();
        List<CouponListResp> couponListResps = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(couponList)) {
            couponListResps = EntityUtils.dtoList2PojoList(couponList, CouponListResp.class);
        }
        jsonResult.setState(0);
        jsonResult.setData(couponListResps);
        return jsonResult;
    }

    @Override
    public JsonResult pages(CouponPagesReq req) {
        JsonResult jsonResult = new JsonResult();
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, new Sort(Sort.Direction.DESC, "periodValidity"));
        Specification<Coupon> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //根据id
            if (StringUtils.isNotBlank(req.getId()))
                list.add(criteriaBuilder.like(root.get("id"), "%" + req.getId() + "%"));
            //根据产品id
            if (StringUtils.isNotBlank(req.getProductId()))
                list.add(criteriaBuilder.like(root.get("productId"), "%" + req.getProductId() + "%"));
            //根据兑换状态
            if (null != req.getState())
                list.add(criteriaBuilder.equal(root.get("state"), req.getState()));
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page<Coupon> page = couponRepository.findAll(specification, pageable);
        List<Coupon> couponList = page.getContent();
        List<CouponDTO> couponListResps = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(couponList)) {
            couponListResps = EntityUtils.dtoList2PojoList(couponList, CouponDTO.class);
        }
        jsonResult.setState(0);
        jsonResult.setData(new PageImpl<>(couponListResps, pageable, page.getTotalElements()));
        return jsonResult;
    }

    @Override
    public JsonResult couponList() {
        JsonResult jsonResult = new JsonResult();
        String accessToken = accessTokenImpl.getAccessToken();
        String requestUrl = Constants.CouponList.replace("ACCESSTOKEN", accessToken);
        String result = restTemplate.getForEntity(requestUrl, String.class).getBody();
        Object rows = JSON.parseObject(result, Map.class).get("rows");
        List<CouponCrmDTO> couponCrmDTOS = JSONObject.parseArray(JSON.toJSONString(rows), CouponCrmDTO.class);
        List<CouponCrmDTO> couponCrmDTOList = new ArrayList<>();
        couponCrmDTOS.forEach(c -> {
            List<Product> productList = productRepository.findAllByCouponId(c.getCouponId());
            if (CollectionUtils.isEmpty(productList)) {
                couponCrmDTOList.add(c);
            }
        });
        jsonResult.setData(0);
        jsonResult.setData(couponCrmDTOList);
        return jsonResult;
    }

    @Override
    public void refresh() {
        String accessToken = accessTokenImpl.getWechatAccessToken();
        String url ="https://api.weixin.qq.com/card/batchget?access_token=TOKEN";
        String cardDetail ="https://api.weixin.qq.com/card/get?access_token=TOKEN";
        String requestUrl = url.replace("TOKEN", accessToken);
        String cardDetailrequestUrl = cardDetail.replace("TOKEN", accessToken);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        JSONObject obj=new JSONObject();
        obj.put("offset",0);
        obj.put("count",50);
        List<String> status_list = new ArrayList<>();
        status_list.add("CARD_STATUS_VERIFY_OK");
        status_list.add("CARD_STATUS_DISPATCH");
        obj.put("status_list",status_list);
        HttpEntity<JSONObject> request = new HttpEntity<JSONObject>(obj, headers);
        String  response = restTemplate.postForObject(requestUrl,request,String.class);
        List<HttpMessageConverter<?>> httpMessageConverters = restTemplate.getMessageConverters();
        httpMessageConverters.stream().forEach(httpMessageConverter -> {
            if(httpMessageConverter instanceof StringHttpMessageConverter){
                StringHttpMessageConverter messageConverter = (StringHttpMessageConverter) httpMessageConverter;
                messageConverter.setDefaultCharset(Charset.forName("UTF-8"));
            }
        });
        JSONObject jo=JSONObject.parseObject(response);
        log.info("accessToken: {}",accessToken);
        log.info("卡券请求返回参数: {}",jo.toJSONString());
        log.info("卡券请求返回参数response"+response);
        int code=jo.getIntValue("errcode");
        if(code==0){
            List<String> cardList = JSON.parseArray(jo.getString("card_id_list"), String.class);
            if(cardList !=null && cardList.size() >0){
                JSONObject objdetail =null;
                List<CrmCoupon> list = new ArrayList<>();
                CrmCoupon coupon =null;
                crmCouponRepository.deleteAllInBatch();
                if(cardList !=null && cardList.size() >0) {
                    for (String cardId : cardList) {
                        objdetail = new JSONObject();
                        objdetail.put("card_id", cardId);
                        HttpEntity<JSONObject> detailrequest = new HttpEntity<JSONObject>(objdetail, headers);
                        String detailresponse = restTemplate.postForObject(cardDetailrequestUrl, detailrequest, String.class);
                        JSONObject jsonObject = JSONObject.parseObject(detailresponse);
                        if (jsonObject.getIntValue("errcode") == 0) {
                            String cardMsg = jsonObject.getString("card");
                            BaseInfo baseInfo = jsonConverString(cardMsg.toLowerCase());
                            coupon = new CrmCoupon();
                            coupon.setId(cardId);
                            coupon.setCouponType(baseInfo.getCardType());
                            coupon.setCouponName(baseInfo.getTitle());
                            coupon.setStartDate(new Date(baseInfo.getDate_info().getBegin_timestamp()));
                            coupon.setEndDate(new Date(baseInfo.getDate_info().getEnd_timestamp()));
                            long total_quantity = baseInfo.getSku().getTotal_quantity();
                            coupon.setTotal((int) total_quantity);
                            coupon.setStore((int) baseInfo.getSku().getQuantity());
                            coupon.setNote(baseInfo.getDescription());
                            coupon.setStartDays((int) baseInfo.getDate_info().getBegin_timestamp());
                            coupon.setValidDays((int) baseInfo.getDate_info().getEnd_timestamp());
                            coupon.setDrawLimit(String.valueOf(baseInfo.getGet_limit()));//每人限领张数
//                            if(StringUtils.isNotEmpty(baseInfo.getDate_info().getType())){
//                                if("date_type_fix_time_range".equals(baseInfo.getDate_info().getType()))
//                                coupon.setValidType()
//                            }
//                            coupon.setValidType(Integer.valueOf(baseInfo.getDate_info().getType()).intValue());
                            coupon.setValidType(1);
                            list.add(coupon);
                        }
                        log.info("卡券详情: {}", jsonObject.toJSONString());
                    }
                    ExecutorService service = Executors.newSingleThreadExecutor();
                    service.execute(() -> {
                        crmCouponRepository.save(list);
                    });
                }
            }
        }else{
            log.info("暂无卡券");
        }
//        List<CouponCrmDTO> couponCrmDTOS = JSONObject.parseArray(JSON.toJSONString(rows), CouponCrmDTO.class);
//        String result = restTemplate.getForEntity(requestUrl, String.class).getBody();
//        Object rows = JSON.parseObject(result, Map.class).get("rows");
//        List<CouponCrmDTO> couponCrmDTOS = JSONObject.parseArray(JSON.toJSONString(rows), CouponCrmDTO.class);
//        log.info("couponCrmDTOS={}", JSON.toJSONString(couponCrmDTOS));
//        List<CrmCoupon> crmCoupons = new ArrayList<>();
//        if (CollectionUtils.isNotEmpty(couponCrmDTOS)) {
//            couponCrmDTOS.forEach(c -> {
//                CrmCoupon crmCoupon = new CrmCoupon();
//                crmCoupon.setId(c.getCouponId());
//                BeanUtils.copyProperties(c, crmCoupon);
//                if (c.getValidType().compareTo(1) == 0) {
//                    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
//                    try {
//                        String endDate = c.getValidDate().getEndDate();
//                        Date endTime = formatter.parse(endDate);
//                        Calendar calendar = Calendar.getInstance();
//                        calendar.setTime(endTime);
//                        calendar.add(Calendar.HOUR, 8);
//                        crmCoupon.setEndDate(calendar.getTime());
//
//                        String startDate = c.getValidDate().getStartDate();
//                        Date startTime = formatter.parse(startDate);
//                        calendar.setTime(startTime);
//                        calendar.add(Calendar.HOUR, 8);
//                        crmCoupon.setStartDate(calendar.getTime());
//                    } catch (ParseException e) {
//                        return;
//                    }
//                } else {
//                    crmCoupon.setStartDays(c.getValidDate().getStartDays());
//                    crmCoupon.setValidDays(c.getValidDate().getValidDays());
//                }
//                crmCoupons.add(crmCoupon);
//            });
//        }
//        crmCouponRepository.save(crmCoupons);
    }

    @Override
    public JsonResult couponPages(BasePageReq req) {
        JsonResult jsonResult = new JsonResult();
        int currentPage = (req.getCurrentPage() - 1) < 0 ? 0 : req.getCurrentPage() - 1;
        int pageSize = req.getPageSize() < 1 ? 10 : req.getPageSize();
        Pageable pageable = new PageRequest(currentPage, pageSize, null);
        Specification<CrmCoupon> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            return criteriaBuilder.and(list.toArray(new Predicate[0]));
        };
        Page<CrmCoupon> page = crmCouponRepository.findAll(specification, pageable);
        List<CrmCoupon> crmCouponList = page.getContent();
        jsonResult.setState(0);
        jsonResult.setData(new PageImpl<>(crmCouponList, pageable, page.getTotalElements()));
        return jsonResult;
    }


    public BaseInfo jsonConverString(String object) {
        JSONObject cardObject=JSONObject.parseObject(object);
        String cardType = cardObject.getString("card_type");
        String type = cardObject.getString(cardType);
        JSONObject result=JSONObject.parseObject(type);
        String baseInfoType = result.getString("base_info");
        JSONObject baseInfoJson=JSONObject.parseObject(baseInfoType);
        BaseInfo baseInfo = JSON.toJavaObject(baseInfoJson, BaseInfo.class);
        baseInfo.setCardType(cardType);
        return baseInfo;
    }
}
